package Cluedo.GUI2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import Cluedo.API.CDialog;
import Cluedo.API.CardImage;
import Cluedo.API.CluedoConfig;
import Cluedo.API.LanguagePack;
import Cluedo.API.NameDictionary;
import Cluedo.API.Resources;
import Cluedo.Game.Card;
import Cluedo.Game.CardCollection;
import Cluedo.Game.Player;

public class SetupGame extends CDialog implements ActionListener {
    
    static final String HTML_ON = "<html><body>";
    static final String HTML_OFF = "</body></html>";
    static final String HTML_NEWLINE = "<br>";
    
    
    NameDictionary nameDictionary = new NameDictionary();
    
    CluedoConfig gameConfig = new CluedoConfig();

    
    // ------------------------------------
    // Rule selection panel
    
    JRadioButton rule1Button = null; 
    JRadioButton rule2Button = null;
    ButtonGroup ruleButtons = new ButtonGroup ();
    
    JButton selectTheseRules = null;
    
    JLabel ruleDescriptionLabel = null;    
    //
    
    // --------------------------------------
    // Map selection Panel
    // --------------------------------------
    
    CardImage []cardsHeld = null;
    CardImage mapImage = null;
    JList mapList ;
    String xmlMaps[];
    JTextArea mapInfo;
    JToggleButton applyButton;
    String mapName = "";
    JPanel picPanel;
    final static String mapFolder = "./Resources/Maps/";
    // --------------------------------------
    // end selection variables
    // --------------------------------------
    
    
    PlayerSelect playerSelect;
    private static final String DEFAULT_GROUP = "setup_game";
    
    public SetupGame(String args) {
        super(args, true);
        
        // Card set loaded before anything else
        gameConfig.setCardSet("default");
        gameConfig.loadCards();
        
        playerSelect = new PlayerSelect(gameConfig);

        
        JButton startButton = new JButton(LanguagePack.getString("start_game", DEFAULT_GROUP));
        JButton cancelButton = new JButton(LanguagePack.getString("cancel_game", DEFAULT_GROUP));
        
        startButton.addActionListener(this);
        startButton.setActionCommand("start_game");
        cancelButton.addActionListener(this);
        cancelButton.setActionCommand("cancel");
        
        getContentPane().add( new JLabel(LanguagePack.getString("main_help_message", DEFAULT_GROUP)), BorderLayout.NORTH );
      
       
        JTabbedPane tabbedPane = new JTabbedPane();
        
        tabbedPane.addTab(LanguagePack.getString("players_tab", DEFAULT_GROUP), playerSelect); // to hide in the Clueme project
/**
 * 
 * The following lines were removed because removing them doesn't cause an effect to the default values of the variables
 * for starting a new game in Cluedo.
 * 
 */
        
//        tabbedPane.addTab(LanguagePack.getString("map_tab", DEFAULT_GROUP), createChooseMapPanel() ); // to hide
//        tabbedPane.addTab(LanguagePack.getString("suspects_tab", DEFAULT_GROUP), new SuspectSelect(gameConfig, playerSelect)); // to hide
//        tabbedPane.addTab(LanguagePack.getString("weapons_tab", DEFAULT_GROUP), new WeaponSelect(gameConfig)); // to hide
        
 //       tabbedPane.addTab(LanguagePack.getString("rules_tab", DEFAULT_GROUP), buildGameRules()); // to hide
        
        getContentPane().add(tabbedPane, BorderLayout.CENTER);
        
        create( new JButton[] {startButton, cancelButton}, -1, -1);
        
        centre();
        setVisible(true);
    }
    
    
    
    // Listeners for the game rules panel
    // @vince CLUEME PROJECT: TO BE REMOVED
    
    ActionListener selectRulesListener = new ActionListener () {
        public void actionPerformed(ActionEvent e) {
            int type = 0;

            if(rule1Button.isSelected() == true) {
                type = 0;
            }
            else if(rule2Button.isSelected() == true) {
                type = 1;
            }
                
            gameConfig.setGameType(type);
        }
        
        };
    ActionListener changeRuleListener = new ActionListener () {
      public void actionPerformed(ActionEvent e) {
          String newCaption = "";
          
          newCaption = addBreaks (LanguagePack.getString(e.getActionCommand() + "_detail", DEFAULT_GROUP));

          ruleDescriptionLabel.setText(newCaption);
      }
        
    };
    
    /**
     * @return
     * @author pscontreras This function just builds the Rules tab in the start game.
     * 		               removing this code or not launching this code means that the default
     * 					   rules will be used in the game
     */
    
//    private JPanel buildGameRules() {
//        JPanel content = new JPanel ();
//        
//        GridBagLayout grid = new GridBagLayout();
//		GridBagConstraints c = new GridBagConstraints();
//		content.setLayout(grid);
//
//
//		String rule1 = LanguagePack.getString("regular_cluedo_rules", DEFAULT_GROUP);
//		String rule2 = LanguagePack.getString("special_rolling_cluedo_rules", DEFAULT_GROUP);
//		
//		rule1Button = new JRadioButton(rule1);
//		rule2Button= new JRadioButton(rule2);
//		
//		rule1Button.setActionCommand("regular_cluedo_rules");
//		rule2Button.setActionCommand("special_rolling_cluedo_rules");
//		
//        rule1Button.addActionListener(changeRuleListener);
//		rule2Button.addActionListener(changeRuleListener);
//		
//		rule1Button.setSelected(true);
//		
//		ruleButtons.add(rule1Button);
//		ruleButtons.add(rule2Button);
//		
//		String rules_panel_message = LanguagePack.getString("rules_panel_message", DEFAULT_GROUP);
//		
//		String rule_description_title = LanguagePack.getString("rule_description_title", DEFAULT_GROUP);
//		JLabel ruleDescriptionTitle = new JLabel (rule_description_title);
//		
//		JLabel caption = new JLabel(rules_panel_message);
//		caption.setFont(new Font("Arial", Font.BOLD, 12));
//		
//		String rule_description = LanguagePack.getString("regular_cluedo_rules_detail", DEFAULT_GROUP);
//		ruleDescriptionLabel = new JLabel(rule_description);
//		ruleDescriptionLabel.setPreferredSize(new Dimension(400, 100));
//		
//		JScrollPane scroller = new JScrollPane(ruleDescriptionLabel);
//		
//		String select_these_rules = LanguagePack.getString("select_rules_button", DEFAULT_GROUP);
//		selectTheseRules = new JButton(select_these_rules);
//		selectTheseRules.addActionListener(selectRulesListener);
//		
//		c.anchor = GridBagConstraints.WEST;
//		
//		JLabel nothing = new JLabel();
//		
//		c.insets.bottom = 30;		
//		c.weightx=2;
//		c.gridwidth = GridBagConstraints.REMAINDER;
//		c.gridx=0;
//		c.gridy=0;
//		grid.setConstraints(nothing, c);
//		
//		c.insets.bottom = 20;
//		c.weightx=1;
//		c.gridx=0;
//		c.gridy++;
//		grid.setConstraints(rule1Button, c);
//
//		c.weightx=1;
//		c.gridx=0;
//		c.gridy++;
//		grid.setConstraints(rule2Button, c);
//
//		c.insets.bottom = 10;
//		c.weightx=1;
//		c.gridx=0;
//		c.gridy++;
//		grid.setConstraints(ruleDescriptionTitle, c);		
//		
//		c.insets.bottom = 30;
//		c.weightx=2;
//		c.gridx=0;
//		c.gridy++;
//		grid.setConstraints(scroller, c);
//		
//
//		c.weightx=1;
//		c.gridx=0;
//		c.gridy++;
//		grid.setConstraints(selectTheseRules, c);
//
//		
//		content.add(nothing);
//		content.add(rule1Button);
//		content.add(rule2Button);
//		content.add(ruleDescriptionTitle);
//		content.add(scroller);
//		content.add(selectTheseRules);
//
//        
//		JPanel wrapper = new JPanel();
//		wrapper.setPreferredSize(new Dimension(200, 300));
//		wrapper.add(caption, BorderLayout.NORTH);
//		wrapper.add(content, BorderLayout.SOUTH);
//
//		return wrapper;
//    }

    /**
     *  @author pscontreras
     *  This function creates the tab for choosing a map
     *  since this function won't be executed, the default map will be used.
     */
    
//    private JPanel createChooseMapPanel(){
//        JPanel content = new JPanel();
//        content.setBorder(BorderFactory.createEtchedBorder() );
//        picPanel = new JPanel();
//        
//        // Layout Panels
//        JPanel overallPanel = new JPanel();
//        overallPanel.setLayout( new BorderLayout(2,20) );
//        JPanel topPanel  = new JPanel();
//        topPanel.setLayout( new BorderLayout() );
//        topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder()) );
//        JPanel middlePanel = new JPanel();
//        middlePanel.setLayout( new BorderLayout(0,5) );
//        JPanel middleLeftPanel = new JPanel();
//        middleLeftPanel.setLayout( new BorderLayout(0,2) );
//        JPanel middleRightPanel = new JPanel();
//        middleRightPanel.setLayout( new BorderLayout(0,5) );
//        middleRightPanel.setPreferredSize( new Dimension (200,30) );
//        JPanel bottomPanel = new JPanel();
//        bottomPanel.setLayout( new BorderLayout(0,3) );
//        
//        // Labels
//        
//        String panelInfo = LanguagePack.getString("choose_map_message", DEFAULT_GROUP);
//        
//        JLabel topLabel = new JLabel(panelInfo);
//        JLabel previewLabel = new JLabel(LanguagePack.getString("preview_map", DEFAULT_GROUP));
//        JLabel dimensionLabel = new JLabel("Dimension: TODO");
//        // TODO: real map dimensions
//        JLabel mapListLabel = new JLabel(LanguagePack.getString("list_map", DEFAULT_GROUP));
//        JLabel authorLabel = new JLabel(LanguagePack.getString("info_map", DEFAULT_GROUP));
//        
//        mapInfo = new JTextArea();
//        
//        
//        JScrollPane scrollMapInfo = new JScrollPane(mapInfo);
//
//        mapInfo.setBackground(Color.lightGray);
//        mapInfo.setBorder( new javax.swing.border.EtchedBorder() );
//        mapInfo.setFont( new Font("Tahoma", Font.PLAIN, 12) );
//        mapInfo.setForeground(Color.BLACK);
//        
//        mapInfo.setColumns(20);
//        mapInfo.setRows(4);
//        
//        mapInfo.setEditable(false);
//        mapInfo.setWrapStyleWord(true);
//        mapInfo.setLineWrap(true);
//        
//        FilenameFilter filter = new FilenameFilter () {
//            public  boolean accept(File dir, String name) {
//                if(name.endsWith(".xml"))
//                    return true;
//                return false;
//            }
//        };
//        
//        xmlMaps = new File(mapFolder).list(filter);
//        
//        for(int i=0; i<xmlMaps.length; i++){
//            xmlMaps[i] = xmlMaps[i].substring(0, xmlMaps[i].length()-4);
//        //    System.out.println(xmlMaps[i]);
//        }
//        
//        
//        mapImage = new CardImage("", "");
//        //TODO : error
//        updateMapPreview(xmlMaps[0]);
//        picPanel.add(mapImage);
//        mapList = new JList(xmlMaps);
//        
//        JScrollPane mapListScroller = new JScrollPane(mapList);
//        mapList.setSelectedIndex(0);
//
//        mapListScroller.setPreferredSize(new Dimension(174,207));
//
//        
//        JPanel scroll = new JPanel();
//
//        scroll.setPreferredSize(new Dimension(268, 178));
//        scroll.add(mapListScroller,BorderLayout.NORTH);
//        
//        // adding the layout Panels
//        topPanel.add(topLabel, BorderLayout.WEST);
//        
//        middleLeftPanel.add(previewLabel, BorderLayout.NORTH);
//        middleLeftPanel.add(picPanel, BorderLayout.CENTER);
//        middleLeftPanel.add(dimensionLabel, BorderLayout.SOUTH);
//        
//        middleRightPanel.add(mapListLabel, BorderLayout.NORTH);
//        middleRightPanel.add(scroll, BorderLayout.CENTER);
//        
//        middlePanel.add(middleLeftPanel, BorderLayout.WEST);
//        middlePanel.add(middleRightPanel, BorderLayout.EAST);
//        
//        String fileName = xmlMaps[mapList.getSelectedIndex()] + "_info.txt";
//        mapInfo.setText(getMapInfo(fileName) );
//        
//        
//        bottomPanel.add(authorLabel, BorderLayout.NORTH);
//        bottomPanel.add(scrollMapInfo, BorderLayout.CENTER);
//        
//        overallPanel.add(topPanel, BorderLayout.NORTH);
//        overallPanel.add(middlePanel, BorderLayout.CENTER);
//        overallPanel.add(bottomPanel, BorderLayout.SOUTH);
//        
//        overallPanel.repaint();
//        content.add(overallPanel);
//        
//        
//        
//        
//        mapList.addListSelectionListener( new ListSelectionListener(){
//            public void valueChanged(ListSelectionEvent e){
//                if(e.getValueIsAdjusting() == true)
//                    return;
//                mapName = xmlMaps[mapList.getSelectedIndex()];
//                updateMapPreview(mapName);
//                gameConfig.setBoardMap(mapName);
//                
//                replaceRoomCards(gameConfig, mapName);
//                
//                mapInfo.setText(getMapInfo(mapName + "_info.txt") );
//            }
//            
//        }
//        );
//        
//        return content;
//    }
    
    /**
     * Replaces all room cards of the old map for those of the new one
     * A synchronized function == used by other functions
     * 
     * @param gameConfig
     * @param mapName
     */
    synchronized private void replaceRoomCards(CluedoConfig gameConfig, String mapName) {
        CardCollection c = gameConfig.getCards();
        System.out.println(c.toXML());
        CardCollection toRemove = new CardCollection();
        
        for(int i =0;i< c.countCards();i++) {
            if(c.cardAt(i).getType().toLowerCase().equals("room"))
                toRemove.insertCard(c.cardAt(i));
        }
        for(int i=0;i<toRemove.countCards();i++)
            c.removeCard(toRemove.cardAt(i));
        
        try {
            StringTokenizer st = new StringTokenizer(Resources.catTextFileExt("Resources/Cards/" + mapName + ".cards",null));
            
            while(st.hasMoreElements() == true) {
                String next = st.nextToken();
                String []parts = next.split(",");
                if(parts.length == 2 && parts[0].charAt(0) != '#')
                    if(parts[1].toLowerCase().equals("room")) {
                        c.insertCard(new Card(parts[0], "Room"), 0);
                    }
                    
            }
            
        } catch (IOException e) {
//            e.printStackTrace();
            //System.out.println(""c.toXML());
        	
        	System.out.println("Where is : " + "Resources/Cards/" + mapName + ".cards ?");
        }
        

        
        
    }
    
    /**
     *This method will return the file info
     *on the given map name
     *  
     * @param fileName
     * @return
     * @throws IOException
     *
     */
    private String getMapInfo(String fileName) {
        String absolutePath = new File("./Resources/Maps/" + fileName).getAbsolutePath();
        StringBuffer info = new StringBuffer();
        
        try {  	
            BufferedReader mapInfoReader = new BufferedReader( new FileReader(absolutePath) );
            
            String line = "";
            while((line = mapInfoReader.readLine()) != null) {
                info.append(line + "\n");
            }
            
            mapInfoReader.close();
        }
        catch(Exception e ) {
            
        }
        
        return info.toString();
    }
    
    /**
     * Changes the map image preview, called from ItemChange event in list of maps.
     * 
     */
    private void updateMapPreview(String mapName) {
        String file = mapFolder + mapName + "_thumb.gif";
        mapImage.changeCard(file, mapName);
        mapImage.repaint();
    }
    
    public void actionPerformed(ActionEvent a) {
        
        if(a.getActionCommand().equals("start_game")) {
            int amount = 0; // variable that holds how many players are needed more
            
            
            if(gameConfig.getPlayers() == null || gameConfig.getPlayers().size() == 0)
            	// no players, just computes how many more needed
                amount = 3; 
            else
                amount = 3-gameConfig.getPlayers().size();
            
            if (gameConfig.getPlayers() == null || gameConfig.getPlayers().size() < 3) { 
            	// players are not enough, shows a dialog box
                JOptionPane.showMessageDialog(null,
                        addArguments(LanguagePack.getString("bad_amount_players", DEFAULT_GROUP), new String[] {""+amount}),
                        "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            else {
            	//if the number of players is correct i.e. more than or equal to 3
            	// and less than or equal to 6
                
                String response = null;
                for(int i = 0; i < gameConfig.getPlayers().size(); i++)
                    System.out.println ( 
                            "[GConfig:] "+((Player)gameConfig.getPlayers().elementAt(i)).getRealName() + " playing as " +  ((Player)gameConfig.getPlayers().elementAt(i)).getCharacter() );
                setInterestingData(gameConfig);
            }
        }
        else {
            setInterestingData(null);
        }
        
        dispose();
    }
    
    /**
     * Used to generate JLabels with line-breaks or additional html, in a user-transparent way
     *
     */
    private String formatString(String data) {
        String output = data;
        
        output = output.replaceAll("\n", HTML_NEWLINE);
        output = HTML_ON + output + HTML_OFF;
        return output;
    }
    
    
    /**
     * Adds relevant arguments to string from String array 
     * 
     * @param string
     * @param names2
     * @return
     */
    private static String addArguments(String string, String[] names2) {
        for(int i=0;i<names2.length;i++)
            string = string.replaceAll("%"+(i+1), names2[i]);
        if(string.indexOf("@@") > -1) {
            string = addBreaks(string);
        }
        return string;
    }
    
    
    /**
     * @param string
     * @return
     */
    private static String addBreaks(String string) {
        string = string.replaceAll("@@", "<br>");
        string = Cluedo.API.Constants.HTML_ON + string + Cluedo.API.Constants.HTML_OFF;
        return string;
    }
    
}